package cn.com.blueInfo.bpm.template.repository.impl;

import cn.com.blueInfo.bpm.common.entity.BaseEntity;
import cn.com.blueInfo.bpm.common.enums.BaseDeleted;
import cn.com.blueInfo.bpm.common.repository.BaseRepository;
import cn.com.blueInfo.bpm.template.entity.NodeDecision;
import cn.com.blueInfo.bpm.template.enums.NodeDecisionType;
import cn.com.blueInfo.bpm.template.mapper.NodeDecisionMapper;
import cn.com.blueInfo.bpm.template.repository.NodeDecisionRepository;
import cn.com.blueInfo.bpm.template.request.NodeDecisionDTO;
import cn.com.blueInfo.core.entity.CurrentLoginUserInfo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 节点流转规则表 数据服务实现类
 * @author suxch
 * @since 2025-09-01 19:30:44
 */
@Log4j2
@Service
public class NodeDecisionRepositoryImpl
        extends ServiceImpl<NodeDecisionMapper, NodeDecision>
        implements NodeDecisionRepository, BaseRepository<NodeDecision, NodeDecisionDTO.QueryDTO> {

    @Autowired
    private CurrentLoginUserInfo currentLoginUserInfo;

    /**
     * 提供获取 CurrentLoginUserInfo 的方法（由实现类提供，避免接口中注入）
     * @return CurrentLoginUserInfo
     */
    @Override
    public CurrentLoginUserInfo getCurrentLoginUserInfo() {
        return currentLoginUserInfo;
    }

    /**
     * 新增节点流转规则
     * @param nodeDecision 节点流转规则参数
     */
    @Override
    public Integer createNodeDecision(NodeDecision nodeDecision) {
        return sqlExecuteResult(save(nodeDecision));
    }

    /**
     * 批量新增节点流转规则
     * @param nodeDecisionList 节点流转规则参数列表
     */
    @Override
    public Integer batchCreateNodeDecision(List<NodeDecision> nodeDecisionList) {
        return sqlExecuteResult(saveBatch(nodeDecisionList), nodeDecisionList.size());
    }

    /**
     * 删除节点流转规则
     * @param nodeDecisionId 节点流转规则ID
     */
    @Override
    public Integer deleteNodeDecision(Long nodeDecisionId) {
        NodeDecision nodeDecision = new NodeDecision();
        nodeDecision.setId(nodeDecisionId);
        nodeDecision.setDeleted(BaseDeleted.DELETED);
        return sqlExecuteResult(removeById(nodeDecision));
    }

    /**
     * 批量删除节点流转规则
     * @param nodeDecisionIdList 节点流转规则ID列表
     */
    @Override
    public Integer batchDeleteNodeDecision(List<Long> nodeDecisionIdList) {
        List<NodeDecision> nodeDecisionList = new ArrayList<>();
        for (Long nodeDecisionId : nodeDecisionIdList) {
            NodeDecision nodeDecision = new NodeDecision();
            nodeDecision.setId(nodeDecisionId);
            nodeDecision.setDeleted(BaseDeleted.DELETED);
            nodeDecisionList.add(nodeDecision);
        }
        return sqlExecuteResult(removeBatchByIds(nodeDecisionList), nodeDecisionList.size());
    }

    /**
     * 更新部分节点流转规则
     * @param nodeDecision 节点流转规则参数
     */
    @Override
    public Integer updateNodeDecisionPartial(NodeDecision nodeDecision) {
        validateUpdateId(nodeDecision.getId());
        LambdaUpdateWrapper<NodeDecision> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(NodeDecision::getId, nodeDecision.getId());
        return sqlExecuteResult(update(updateWrapper));
    }

    /**
     * 更新全部节点流转规则
     * @param nodeDecision 节点流转规则参数
     */
    @Override
    public Integer updateNodeDecision(NodeDecision nodeDecision) {
        validateUpdateId(nodeDecision.getId());
        return sqlExecuteResult(updateById(nodeDecision));
    }

    /**
     * 查询一条节点流转规则
     * @param nodeDecisionId 节点流转规则ID
     */
    @Override
    public NodeDecision getNodeDecisionById(Long nodeDecisionId) {
        LambdaQueryWrapper<NodeDecision> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(NodeDecision::getId, nodeDecisionId);
        return getOne(queryWrapper);
    }

    /**
     * 分页查询节点流转规则
     * @param nodeDecisionQueryDTO 节点流转规则参数
     */
    @Override
    public Page<NodeDecision> getNodeDecisionPage(NodeDecisionDTO.QueryDTO nodeDecisionQueryDTO) {
        Page<NodeDecision> nodeDecisionPage = new Page<>(
                nodeDecisionQueryDTO.getPage(), nodeDecisionQueryDTO.getSize());
        LambdaQueryWrapper<NodeDecision> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper(queryWrapper, nodeDecisionQueryDTO);

        BaseDeleted deleted = nodeDecisionQueryDTO.getDeleted();
        if (ObjectUtils.isNotEmpty(deleted) && deleted.equals(BaseDeleted.DELETED)) {
            return baseMapper.selectDeletePage(nodeDecisionPage, queryWrapper);
        } else {
            return page(nodeDecisionPage, queryWrapper);
        }
    }

    /**
     * 根据条件查询 节点流转规则 数量
     * @param nodeDecisionQueryDTO 节点流转规则参数
     */
    @Override
    public Long getNodeDecisionCount(NodeDecisionDTO.QueryDTO nodeDecisionQueryDTO) {
        LambdaQueryWrapper<NodeDecision> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper(queryWrapper, nodeDecisionQueryDTO);

        BaseDeleted deleted = nodeDecisionQueryDTO.getDeleted();
        if (ObjectUtils.isNotEmpty(deleted) && deleted.equals(BaseDeleted.DELETED)) {
            return baseMapper.selectDeleteCount(queryWrapper);
        } else {
            return count(queryWrapper);
        }
    }

    /**
     * 根据条件查询 节点流转规则
     * @param nodeDecisionQueryDTO 节点流转规则参数
     */
    @Override
    public List<NodeDecision> getNodeDecisionList(NodeDecisionDTO.QueryDTO nodeDecisionQueryDTO) {
        LambdaQueryWrapper<NodeDecision> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper(queryWrapper, nodeDecisionQueryDTO);

        BaseDeleted deleted = nodeDecisionQueryDTO.getDeleted();
        if (ObjectUtils.isNotEmpty(deleted) && deleted.equals(BaseDeleted.DELETED)) {
            return baseMapper.selectDeleteList(queryWrapper);
        } else {
            return list(queryWrapper);
        }
    }

    private void queryWrapper(LambdaQueryWrapper<NodeDecision> queryWrapper,
                              NodeDecisionDTO.QueryDTO nodeDecisionQueryDTO) {

        Long processId = nodeDecisionQueryDTO.getProcessId();
        queryWrapper.eq(ObjectUtils.isNotEmpty(processId), NodeDecision::getProcessId, processId);

        Long currentNodeId = nodeDecisionQueryDTO.getCurrentNodeId();
        queryWrapper.eq(ObjectUtils.isNotEmpty(currentNodeId), NodeDecision::getCurrentNodeId, currentNodeId);

        String decisionName = nodeDecisionQueryDTO.getDecisionName();
        queryWrapper.eq(StringUtils.isNotBlank(decisionName), NodeDecision::getDecisionName, decisionName);

        NodeDecisionType decisionType = nodeDecisionQueryDTO.getDecisionType();
        queryWrapper.eq(ObjectUtils.isNotEmpty(decisionType), NodeDecision::getDecisionType, decisionType);

        Integer priority = nodeDecisionQueryDTO.getPriority();
        queryWrapper.eq(ObjectUtils.isNotEmpty(priority), NodeDecision::getPriority, priority);

        Long prevNodeId = nodeDecisionQueryDTO.getPrevNodeId();
        queryWrapper.eq(ObjectUtils.isNotEmpty(prevNodeId), NodeDecision::getPrevNodeId, prevNodeId);

        Long nextNodeId = nodeDecisionQueryDTO.getNextNodeId();
        queryWrapper.eq(ObjectUtils.isNotEmpty(nextNodeId), NodeDecision::getNextNodeId, nextNodeId);

        String conditionExpr = nodeDecisionQueryDTO.getConditionExpr();
        queryWrapper.eq(StringUtils.isNotBlank(conditionExpr), NodeDecision::getConditionExpr, conditionExpr);

        String defaultOpinion = nodeDecisionQueryDTO.getDefaultOpinion();
        queryWrapper.eq(StringUtils.isNotBlank(defaultOpinion), NodeDecision::getDefaultOpinion, defaultOpinion);

        String submitFunc = nodeDecisionQueryDTO.getSubmitFunc();
        queryWrapper.eq(StringUtils.isNotBlank(submitFunc), NodeDecision::getSubmitFunc, submitFunc);

        addQueryWrapper(queryWrapper, nodeDecisionQueryDTO, getCommonColumn());

    }

    private Map<String, SFunction<NodeDecision, ?>> getCommonColumn() {
        return BaseEntity.getCommonColumn(
                NodeDecision::getOrderNumber,
                NodeDecision::getTenantId,
                NodeDecision::getApplicationId,
                NodeDecision::getStatus,
                NodeDecision::getDeleted,
                NodeDecision::getDeleteUserId,
                NodeDecision::getDeleteTime,
                NodeDecision::getRemark,
                NodeDecision::getCreateUserId,
                NodeDecision::getCreateTime,
                NodeDecision::getUpdateUserId,
                NodeDecision::getUpdateTime,
                NodeDecision::getExtend1,
                NodeDecision::getExtend2,
                NodeDecision::getExtend3);
    }

}
